---
title: "06-Java 深拷贝与浅拷贝"
aliases:
- "Java 深拷贝与浅拷贝"
created: 2025-12-25
---
# Java 深拷贝与浅拷贝
---
## 一、概念总览
### **1.1 三种拷贝方式对比**
```mermaid
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#fdfdfd"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
graph TB
%% 样式定义
classDef refStyle fill:#e3f2fd,stroke:#2196f3,stroke-width:2px,color:#0d47a1;
classDef shallowStyle fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100;
classDef deepStyle fill:#f1f8e9,stroke:#4caf50,stroke-width:2px,color:#1b5e20;
classDef titleStyle fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px,color:#333,font-weight:bold;
MainTitle(["Java 对象拷贝方式总览"])
subgraph SourceObject ["原始对象 A (Memory Structure)"]
A_Data["name = '张三'"]
A_Addr["address"]
Target[("Address Object: 北京")]
A_Addr -- "引用指向" --> Target
end
subgraph CopyTypes ["三种拷贝机制对比"]
direction LR
subgraph RefCopy ["引用拷贝 (Reference Copy)"]
R1["两个引用指向同一对象"]
R2["A == B (地址相同)"]
R3["修改 B 会影响 A"]
end
subgraph ShallowCopy ["浅拷贝 (Shallow Copy)"]
S1["创建新对象 B"]
S2["基本类型拷贝值"]
S3["引用类型共享地址"]
end
subgraph DeepCopy ["深拷贝 (Deep Copy)"]
D1["完全独立的新对象"]
D2["递归拷贝所有层级"]
D3["修改 B 对 A 无影响"]
end
end
subgraph Comparison ["底层效果直观对比"]
C1["B ──┐
├─> [同一个对象]
A ──┘"]
C2["B (新对象) ──> [共享 Address]
A (原对象) ──> [共享 Address]"]
C3["B (新对象) ──> [新 Address]
A (原对象) ──> [原 Address]"]
end
%% 连接逻辑
MainTitle --> SourceObject
SourceObject --> CopyTypes
RefCopy ==> C1
ShallowCopy ==> C2
DeepCopy ==> C3
%% 应用样式
class RefCopy,R1,R2,R3,C1 refStyle;
class ShallowCopy,S1,S2,S3,C2 shallowStyle;
class DeepCopy,D1,D2,D3,C3 deepStyle;
class MainTitle titleStyle;
class SourceObject,A_Data,A_Addr,Target titleStyle;
```
### **1.2 一句话定义**
| **拷贝类型** | **定义** | **修改影响** |
| --- | --- | --- |
| **引用拷贝** | 复制引用地址,两个引用指向同一对象 | 完全影响 |
| **浅拷贝** | 创建新对象,但内部引用类型属性共享 | 部分影响 |
| **深拷贝** | 创建新对象,所有层级都是全新的 | 互不影响 |
---
---
## 二、引用拷贝
### **2.1 概念图解**
```mermaid
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart LR
%% 样式定义
classDef stackStyle fill:#e3f2fd,stroke:#2196f3,stroke-width:2px,color:#0d47a1;
classDef heapStyle fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100;
classDef codeStyle fill:#f5f5f5,stroke:#9e9e9e,stroke-dasharray: 5 5,color:#333;
classDef noteStyle fill:#e8f5e9,stroke:#4caf50,stroke-width:1px,color:#1b5e20;
%% 顶部代码展示
Code["代码:Person p2 = p1;"]:::codeStyle
subgraph Memory ["内存布局 (引用拷贝)"]
direction LR
subgraph Stack ["栈内存 (Stack)"]
P1["p1 = 0x100"]:::stackStyle
P2["p2 = 0x100"]:::stackStyle
end
subgraph Heap ["堆内存 (Heap)"]
Object["Person 对象
name = '张三'
age = 20
地址: 0x100"]:::heapStyle
end
%% 引用指向
P1 ==> Object
P2 ==> Object
end
%% 特点描述
Features["特点说明:
• 没有创建新对象
• 两个引用指向同一个内存地址
• 修改 p1 会同步反映在 p2 上"]:::noteStyle
%% 布局辅助
Code ~~~ Memory
Memory ~~~ Features
```
### **2.2 代码示例**
```java
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Getter 和 Setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
/**
* 引用拷贝测试
*/
public class ReferenceCopyDemo {
public static void main(String[] args) {
Person p1 = new Person("张三", 20);
// ===== 引用拷贝 =====
Person p2 = p1; // 只是复制了引用地址
System.out.println("===== 修改前 =====");
System.out.println("p1: " + p1);
System.out.println("p2: " + p2);
System.out.println("p1 == p2: " + (p1 == p2)); // true
// 通过 p2 修改
p2.setAge(25);
p2.setName("李四");
System.out.println("\n===== 通过 p2 修改后 =====");
System.out.println("p1: " + p1); // p1 也变了!
System.out.println("p2: " + p2);
}
}
```
**输出结**果:
```
===== 修改前 =====
p1: Person{name='张三', age=20}
p2: Person{name='张三', age=20}
p1 == p2: true
===== 通过 p2 修改后 =====
p1: Person{name='李四', age=25}
p2: Person{name='李四', age=25}
```
---
## 三、浅拷贝
### **3.1 概念图解**
```mermaid
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
graph LR
%% 定义样式
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
subgraph Stack ["栈内存 (Stack)"]
P1_Ref["p1 = 0x100"]
P2_Ref["p2 = 0x200"]
end
subgraph Heap ["堆内存 (Heap)"]
subgraph Object1 ["Person 对象 (0x100)"]
P1_Data["name: '张三'
age: 20
address: 0x300"]
end
subgraph Object2 ["Person 对象 (0x200)"]
P2_Data["name: '张三'
age: 20
address: 0x300"]
end
Addr_Obj[("Address 对象 (0x300)
city: '北京'")]
end
%% 连线关系
P1_Ref ==> Object1
P2_Ref ==> Object2
P1_Data -. "引用共享" .-> Addr_Obj
P2_Data -. "引用共享" .-> Addr_Obj
%% 注释说明
Note1["浅拷贝特点
1. 创建了新对象实例
2. 基本类型值复制
3. 引用类型仅复制地址"]
%% 应用样式
class P1_Ref,P2_Ref main;
class Addr_Obj storage;
class Note1 term;
class Object1,Object2 decision;
%% 布局辅助
Note1 ~~~ Stack
```
### **3.2 实现方式:Cloneable 接口**
```java
/**
* 地址类(引用类型属性)
*/
public class Address {
private String city;
private String street;
public Address(String city, String street) {
this.city = city;
this.street = street;
}
// Getter 和 Setter
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public String getStreet() { return street; }
public void setStreet(String street) { this.street = street; }
@Override
public String toString() {
return "Address{city='" + city + "', street='" + street + "'}";
}
}
/**
* Person 类实现浅拷贝
*/
public class Person implements Cloneable {
private String name; // String 是不可变对象,特殊处理
private int age; // 基本类型
private Address address; // 引用类型
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
/**
* 浅拷贝实现
*/
@Override
public Person clone() {
try {
return (Person) super.clone(); // Object.clone() 是浅拷贝
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
// Getter 和 Setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public Address getAddress() { return address; }
public void setAddress(Address address) { this.address = address; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + ", address=" + address + "}";
}
}
```
### **3.3 浅拷贝测试**
```java
public class ShallowCopyDemo {
public static void main(String[] args) {
// 创建原始对象
Address address = new Address("北京", "长安街");
Person p1 = new Person("张三", 20, address);
// ===== 浅拷贝 =====
Person p2 = p1.clone();
System.out.println("===== 拷贝后初始状态 =====");
System.out.println("p1: " + p1);
System.out.println("p2: " + p2);
System.out.println("p1 == p2: " + (p1 == p2)); // false(不同对象)
System.out.println("p1.address == p2.address: " + (p1.getAddress() == p2.getAddress())); // true(共享)
// ===== 测试 1:修改基本类型属性 =====
p2.setAge(25);
System.out.println("\n===== 修改 p2 的 age 后 =====");
System.out.println("p1.age: " + p1.getAge()); // 20(不受影响)
System.out.println("p2.age: " + p2.getAge()); // 25
// ===== 测试 2:修改引用类型属性的内容 =====
p2.getAddress().setCity("上海");
System.out.println("\n===== 修改 p2 的 address.city 后 =====");
System.out.println("p1.address: " + p1.getAddress()); // 上海(被影响!)
System.out.println("p2.address: " + p2.getAddress()); // 上海
// ===== 测试 3:替换整个引用 =====
p2.setAddress(new Address("广州", "天河路"));
System.out.println("\n===== 替换 p2 的整个 address 后 =====");
System.out.println("p1.address: " + p1.getAddress()); // 上海(不受影响)
System.out.println("p2.address: " + p2.getAddress()); // 广州
}
}
```
**输出结**果:
```
===== 拷贝后初始状态 =====
p1: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}}
p2: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}}
p1 == p2: false
p1.address == p2.address: true
===== 修改 p2 的 age 后 =====
p1.age: 20
p2.age: 25
===== 修改 p2 的 address.city 后 =====
p1.address: Address{city='上海', street='长安街'}
p2.address: Address{city='上海', street='长安街'}
===== 替换 p2 的整个 address 后 =====
p1.address: Address{city='上海', street='长安街'}
p2.address: Address{city='广州', street='天河路'}
```
### **3.4 Object.clone() 源码分析**
```
/**
* Object 类中的 clone 方法(native 方法)
*/
protected native Object clone() throws CloneNotSupportedException;
```
```mermaid
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart TB
%% 样式定义
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
classDef error fill:#ffebee,stroke:#f44336,stroke-width:1.5px,color:#b71c1c;
classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
Start(["开始调用 Object.clone()"]) --> CheckInterface{"是否实现
Cloneable 接口?"}
%% 异常分支
CheckInterface -- 否 --> ThrowEx[/"抛出 CloneNotSupportedException"/]
class ThrowEx error
%% 正常流程
CheckInterface == 是 ==> Allocate["创建新对象
(分配内存空间)"]
class Allocate main
Allocate ==> FieldCopy[["执行字段复制 (Field Copy)"]]
subgraph CopyDetail [" 字段复制机制 (浅拷贝) "]
direction TB
Primitive["基本类型
(int, double, boolean...)"] -- 直接复制值 --> Value["新旧对象值相同"]
Reference["引用类型
(对象、数组)"] -- 复制引用地址 --> Address["指向堆中同一个对象"]
end
FieldCopy --- CopyDetail
CopyDetail ==> Return(["返回新对象的引用"])
class Return term
%% 节点样式应用
class CheckInterface decision
class FieldCopy main
class Primitive,Reference storage
```
---
## 四、深拷贝
### **4.1 概念图解**
```mermaid
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart LR
%% 样式定义
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
classDef highlight fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100;
%% 栈内存区域
subgraph Stack ["栈内存 (Stack)"]
P1_Ref["p1 = 0x100"]
P2_Ref["p2 = 0x200"]
end
%% 堆内存区域
subgraph Heap ["堆内存 (Heap)"]
%% P1 的对象结构
subgraph P1_Area ["原始对象 P1"]
P1_Obj["Person 对象 (0x100)
name: '张三'
age: 20"]
P1_Addr_Ref["address (指向 0x300)"]
end
%% P2 的对象结构
subgraph P2_Area ["克隆对象 P2"]
P2_Obj["Person 对象 (0x200)
name: '张三'
age: 20"]
P2_Addr_Ref["address (指向 0x400)"]
end
%% Address 对象
Addr1[("Address 对象 (0x300)
city: '北京'")]
Addr2[("Address 对象 (0x400)
city: '北京'")]
end
%% 逻辑连接
P1_Ref ==> P1_Obj
P2_Ref ==> P2_Obj
P1_Obj --- P1_Addr_Ref
P1_Addr_Ref --> Addr1
P2_Obj --- P2_Addr_Ref
P2_Addr_Ref --> Addr2
%% 独立性说明
Status{"完全独立"}
Addr1 -.-> Status
Addr2 -.-> Status
%% 应用样式
class P1_Ref,P2_Ref main;
class Addr1,Addr2 storage;
class Status highlight;
%% 标注
Note1["代码:Person p2 = p1.deepClone();"]
Note1 ~~~ Stack
```
### **4.2 实现方式一:手动递归拷贝**
```java
/**
* Address 类 - 支持深拷贝
*/
public class Address implements Cloneable {
private String city;
private String street;
public Address(String city, String street) {
this.city = city;
this.street = street;
}
/**
* Address 自己的 clone 方法
*/
@Override
public Address clone() {
try {
return (Address) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
// Getter/Setter/toString 省略
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public String getStreet() { return street; }
public void setStreet(String street) { this.street = street; }
@Override
public String toString() {
return "Address{city='" + city + "', street='" + street + "'}";
}
}
/**
* Person 类 - 实现深拷贝
*/
public class Person implements Cloneable {
private String name;
private int age;
private Address address;
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
/**
* 深拷贝实现:递归调用内部对象的 clone
*/
@Override
public Person clone() {
try {
Person cloned = (Person) super.clone();
// 关键:对引用类型属性也进行拷贝
if (this.address != null) {
cloned.address = this.address.clone();
}
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
// Getter/Setter 省略
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public Address getAddress() { return address; }
public void setAddress(Address address) { this.address = address; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + ", address=" + address + "}";
}
}
```
### **4.3 深拷贝测试**
```java
public class DeepCopyDemo {
public static void main(String[] args) {
// 创建原始对象
Address address = new Address("北京", "长安街");
Person p1 = new Person("张三", 20, address);
// ===== 深拷贝 =====
Person p2 = p1.clone();
System.out.println("===== 拷贝后初始状态 =====");
System.out.println("p1: " + p1);
System.out.println("p2: " + p2);
System.out.println("p1 == p2: " + (p1 == p2));
System.out.println("p1.address == p2.address: " + (p1.getAddress() == p2.getAddress()));
// ===== 修改 p2 的 address.city =====
p2.getAddress().setCity("上海");
System.out.println("\n===== 修改 p2 的 address.city 后 =====");
System.out.println("p1.address: " + p1.getAddress()); // 北京(不受影响!)
System.out.println("p2.address: " + p2.getAddress()); // 上海
}
}
```
**输出结果**:
```
===== 拷贝后初始状态 =====
p1: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}}
p2: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}}
p1 == p2: false
p1.address == p2.address: false
===== 修改 p2 的 address.city 后 =====
p1.address: Address{city='北京', street='长安街'}
p2.address: Address{city='上海', street='长安街'}
```
### **4.4 实现方式二:序列化方式(推荐)**
```java
import java.io.*;
/**
* 使用序列化实现深拷贝
*/
public class DeepCopyUtil {
/**
* 通过序列化实现深拷贝
* 要求:对象及其所有属性都必须实现 Serializable 接口
*/
@SuppressWarnings("unchecked")
public static T deepCopy(T object) {
try {
// 1. 将对象写入字节流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.close();
// 2. 从字节流读取对象
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
T copy = (T) ois.readObject();
ois.close();
return copy;
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException("深拷贝失败", e);
}
}
}
/**
* 实体类需要实现 Serializable
*/
public class Address implements Serializable {
private static final long serialVersionUID = 1L;
private String city;
private String street;
// ... 其他代码
}
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private Address address;
// ... 其他代码
}
/**
* 使用示例
*/
public class SerializationDeepCopyDemo {
public static void main(String[] args) {
Address address = new Address("北京", "长安街");
Person p1 = new Person("张三", 20, address);
// 深拷贝
Person p2 = DeepCopyUtil.deepCopy(p1);
System.out.println("p1.address == p2.address: " + (p1.getAddress() == p2.getAddress()));
// false(完全独立)
p2.getAddress().setCity("上海");
System.out.println("p1.address.city: " + p1.getAddress().getCity()); // 北京
System.out.println("p2.address.city: " + p2.getAddress().getCity()); // 上海
}
}
```
### **4.5 实现方式三:JSON 序列化(第三方库)**
```java
import com.google.gson.Gson;
// 或者
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* 使用 Gson 实现深拷贝
*/
public class JsonDeepCopy {
private static final Gson gson = new Gson();
public static T deepCopy(T object, Class clazz) {
String json = gson.toJson(object);
return gson.fromJson(json, clazz);
}
}
/**
* 使用 Jackson 实现深拷贝
*/
public class JacksonDeepCopy {
private static final ObjectMapper mapper = new ObjectMapper();
public static T deepCopy(T object, Class clazz) {
try {
String json = mapper.writeValueAsString(object);
return mapper.readValue(json, clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
// 使用示例
Person p2 = JsonDeepCopy.deepCopy(p1, Person.class);
```
### **4.6 深拷贝实现方式对比**
| **实现方式** | **优点** | **缺点** | **适用场景** |
| --- | --- | --- | --- |
| **手动递归** | 性能最好,可定制 | 代码量大,易遗漏 | 简单对象 |
| **序列化** | 通用,自动处理嵌套 | 性能较差,需实现 Serializable | 复杂对象 |
| **JSON** | 简单,无需特殊接口 | 性能一般,需引入依赖 | 与前端交互的对象 |
| **拷贝构造器** | 直观,可控 | 每个类都要写 | 明确需要拷贝的类 |
---
---
## 五、三种拷贝对比
### **5.1 完整对比图**
```mermaid
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart TB
%% 样式定义
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
classDef note fill:#fafafa,stroke:#9e9e9e,stroke-dasharray: 5 5;
subgraph RefCopy ["引用拷贝 (Reference Copy)"]
direction LR
R_p1["p1 (引用)"]
R_p2["p2 (引用)"]
R_Obj1[["Person 对象"]]
R_Addr1[("Address 对象")]
R_p1 --> R_Obj1
R_p2 --> R_Obj1
R_Obj1 -- "address 属性" --> R_Addr1
R_Note["✗ 没有创建新对象
✗ 修改任何属性都互相影响"]
class R_Note note
end
subgraph ShallowCopy ["浅拷贝 (Shallow Copy)"]
direction LR
S_p1["p1 (引用)"]
S_p2["p2 (引用)"]
S_Obj1[["Person 对象 (原)"]]
S_Obj2[["Person 对象 (新)"]]
S_Addr1[("Address 对象 (共享)")]
S_p1 --> S_Obj1
S_p2 --> S_Obj2
S_Obj1 -- "address" --> S_Addr1
S_Obj2 -- "address" --> S_Addr1
S_Note["✓ 创建了新 Person 对象
✓ 基本类型独立
✗ 引用类型属性共享"]
class S_Note note
end
subgraph DeepCopy ["深拷贝 (Deep Copy)"]
direction LR
D_p1["p1 (引用)"]
D_p2["p2 (引用)"]
D_Obj1[["Person 对象 (原)"]]
D_Obj2[["Person 对象 (新)"]]
D_Addr1[("Address 对象 (原)")]
D_Addr2[("Address 对象 (新)")]
D_p1 --> D_Obj1
D_p2 --> D_Obj2
D_Obj1 -- "address" --> D_Addr1
D_Obj2 -- "address" --> D_Addr2
D_Note["✓ 所有属性完全独立
✓ 递归复制引用对象
✓ 完全互不影响"]
class D_Note note
end
%% 应用样式
class R_p1,R_p2,S_p1,S_p2,D_p1,D_p2 main
class R_Obj1,S_Obj1,S_Obj2,D_Obj1,D_Obj2 decision
class R_Addr1,S_Addr1,D_Addr1,D_Addr2 storage
```
### **5.2 修改影响对比表**
| **操作** | **引用拷贝** | **浅拷贝** | **深拷贝** |
| --- | --- | --- | --- |
| 修改 p2.age(基本类型) | p1 受影响 | p1 不受影响 | p1 不受影响 |
| 修改 p2.name(String,不可变) | p1 受影响 | p1 不受影响\* | p1 不受影响 |
| 修改 p2.address.city | p1 受影响 | **p1 受影响** | p1 不受影响 |
| 替换 p2.address = new Address() | p1 受影响 | p1 不受影响 | p1 不受影响 |
> *\*注:String 是不可变对象,重新赋值会创建新对象,所以表现得像深拷贝。*
---
### **5.3 综合测试代码**
```java
public class CopyComparisonDemo {
public static void main(String[] args) {
System.out.println("========== 1. 引用拷贝 ==========");
testReferenceCopy();
System.out.println("\n========== 2. 浅拷贝 ==========");
testShallowCopy();
System.out.println("\n========== 3. 深拷贝 ==========");
testDeepCopy();
}
static void testReferenceCopy() {
Person p1 = new Person("张三", 20, new Address("北京", "长安街"));
Person p2 = p1; // 引用拷贝
p2.getAddress().setCity("上海");
System.out.println("修改 p2.address.city 后:");
System.out.println("p1.address.city = " + p1.getAddress().getCity()); // 上海
System.out.println("p2.address.city = " + p2.getAddress().getCity()); // 上海
System.out.println("结论: p1 受影响");
}
static void testShallowCopy() {
Person p1 = new Person("张三", 20, new Address("北京", "长安街"));
Person p2 = p1.shallowClone(); // 浅拷贝
p2.getAddress().setCity("上海");
System.out.println("修改 p2.address.city 后:");
System.out.println("p1.address.city = " + p1.getAddress().getCity()); // 上海
System.out.println("p2.address.city = " + p2.getAddress().getCity()); // 上海
System.out.println("结论: p1 受影响(共享内部对象)");
}
static void testDeepCopy() {
Person p1 = new Person("张三", 20, new Address("北京", "长安街"));
Person p2 = p1.deepClone(); // 深拷贝
p2.getAddress().setCity("上海");
System.out.println("修改 p2.address.city 后:");
System.out.println("p1.address.city = " + p1.getAddress().getCity()); // 北京
System.out.println("p2.address.city = " + p2.getAddress().getCity()); // 上海
System.out.println("结论: p1 不受影响(完全独立)");
}
}
```
---
## 六、复杂场景:多层嵌套
### **6.1 多层嵌套对象**
```java
/**
* 公司类(多层嵌套示例)
*/
public class Company implements Serializable, Cloneable {
private String name;
private Address headquarters; // 第1层嵌套
private List departments; // 集合嵌套
// 深拷贝(手动实现)
@Override
public Company clone() {
try {
Company cloned = (Company) super.clone();
// 拷贝 Address
if (this.headquarters != null) {
cloned.headquarters = this.headquarters.clone();
}
// 拷贝 List
if (this.departments != null) {
cloned.departments = new ArrayList<>();
for (Department dept : this.departments) {
cloned.departments.add(dept.clone()); // 每个元素都要 clone
}
}
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
/**
* 部门类
*/
public class Department implements Serializable, Cloneable {
private String name;
private List employees; // 第2层嵌套
@Override
public Department clone() {
try {
Department cloned = (Department) super.clone();
if (this.employees != null) {
cloned.employees = new ArrayList<>();
for (Employee emp : this.employees) {
cloned.employees.add(emp.clone());
}
}
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
```
### **6.2 多层嵌套图示**
```mermaid
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart TB
subgraph ShallowCopy ["浅拷贝 (Shallow Copy) - 仅复制顶层"]
direction LR
S_Orig["原对象 Company"]
S_Addr["Address 对象"]
S_List["List 集合"]
S_Dept["Department 对象"]
S_Emp["Employee 对象"]
S_New["新对象 Company"]
S_Orig --> S_Addr
S_Orig --> S_List
S_List --> S_Dept
S_Dept --> S_Emp
S_New == "引用相同地址" ==> S_Addr
S_New == "引用相同地址" ==> S_List
end
subgraph DeepCopy ["深拷贝 (Deep Copy) - 递归复制所有层级"]
direction TB
subgraph OriginalTree ["原始对象树"]
direction LR
O_Comp["Company"] --> O_Addr["Address"]
O_Addr --> O_List["List"]
O_List --> O_Dept["Department"]
O_Dept --> O_Emp["Employee"]
end
subgraph NewTree ["全新副本树"]
direction LR
N_Comp["Company"] --> N_Addr["Address"]
N_Addr --> N_List["List"]
N_List --> N_Dept["Department"]
N_Dept --> N_Emp["Employee"]
end
O_Comp -. "独立副本" .-> N_Comp
O_Addr -. "独立副本" .-> N_Addr
O_List -. "独立副本" .-> N_List
O_Dept -. "独立副本" .-> N_Dept
O_Emp -. "独立副本" .-> N_Emp
end
subgraph Tips ["💡 最佳实践"]
T1["复杂对象推荐使用序列化/反序列化 (JSON/Protobuf)"]
T2["手动实现需注意循环引用问题"]
end
%% 样式定义
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
class S_New,N_Comp,N_Addr,N_List,N_Dept,N_Emp main;
class S_Orig,O_Comp,O_Addr,O_List,O_Dept,O_Emp storage;
class T1,T2 decision;
```
---
## 七、特殊情况处理
### **7.1 不可变对象**
```mermaid
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart TB
subgraph Core ["不可变对象核心逻辑"]
direction TB
ObjType(["不可变对象 (Immutable Objects)"])
Examples["String, Integer, LocalDate"]
Features{{"核心特点"}}
F1["创建后状态不可改变"]
F2["修改操作 = 返回新对象"]
Strategy{{"拷贝处理策略"}}
S1["直接引用共享 (Shallow Share)"]
S2["无需深拷贝 (Deep Copy Not Needed)"]
end
subgraph Example ["内存变化示例: String name = '张三'"]
direction LR
State1["栈变量: name"] -- "初始指向" --> Val1[("堆内存: '张三'")]
Update["执行: name = '李四'"]
State1 == "重定向" ==> Val2[("堆内存: '李四'")]
Val1 -. "原对象保持不变" .-> Val1
end
%% 节点连接
ObjType --- Examples
Examples --> Features
Features --> F1
Features --> F2
F1 & F2 --> Strategy
Strategy --> S1
Strategy --> S2
S1 ==> Example
%% 样式定义
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
class ObjType,Examples main;
class Features,Strategy decision;
class F1,F2,S1,S2 term;
class Val1,Val2 storage;
```
### **7.2 数组的拷贝**
```java
public class ArrayCopyDemo {
public static void main(String[] args) {
// ===== 一维基本类型数组 =====
int[] arr1 = {1, 2, 3};
int[] arr2 = arr1.clone(); // 深拷贝
arr2[0] = 100;
System.out.println(arr1[0]); // 1(不受影响)
// ===== 一维引用类型数组 =====
Person[] persons1 = {new Person("张三", 20, null)};
Person[] persons2 = persons1.clone(); // 浅拷贝!
persons2[0].setName("李四");
System.out.println(persons1[0].getName()); // 李四(受影响!)
// ===== 二维数组 =====
int[][] matrix1 = {{1, 2}, {3, 4}};
int[][] matrix2 = matrix1.clone(); // 浅拷贝!
matrix2[0][0] = 100;
System.out.println(matrix1[0][0]); // 100(受影响!)
// ===== 二维数组深拷贝 =====
int[][] matrix3 = new int[matrix1.length][];
for (int i = 0; i < matrix1.length; i++) {
matrix3[i] = matrix1[i].clone(); // 每行单独 clone
}
}
}
```
**数组拷贝总结**:
| **数组类型** | `clone()` **/** `Arrays.copyOf()` | **效果** |
| --- | --- | --- |
| 一维基本类型 | 深拷贝 | ✅ 独立 |
| 一维引用类型 | 浅拷贝 | ⚠️ 元素共享 |
| 二维数组 | 浅拷贝 | ⚠️ 行数组共享 |
---
## 八、最佳实践与总结
### **8.1 选择建议**
```mermaid
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
graph TB
%% 样式定义
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
classDef highlight fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
subgraph SelectionGuide ["对象拷贝选择建议"]
direction TB
Start(["开始判断"]) --> Q1{"需要拷贝对象吗?"}
Q1 -- "只读使用" --> Result1["引用拷贝
(无需物理拷贝)"]
Q1 -- "需要修改" --> Q2{"对象包含引用属性?"}
Q2 -- "没有" --> Result2["浅拷贝
(Shallow Copy)"]
Q2 -- "有" --> Q3{"内部引用也需要
独立修改吗?"}
Q3 -- "否" --> Result3["浅拷贝"]
Q3 -- "是" --> Result4["深拷贝
(Deep Copy)"]
end
%% 节点分类应用
class Start main;
class Q1,Q2,Q3 decision;
class Result1,Result2,Result3 term;
class Result4 highlight;
%% 核心路径加粗
Q2 == "有" ==> Q3
Q3 == "是" ==> Result4
%% 补充说明样式
style SelectionGuide fill:#fcfcfc,stroke:#d1d1d1,stroke-dasharray: 5 5;
```
### **8.2 实现方式选择**
| **场景** | **推荐方式** | **原因** |
| --- | --- | --- |
| 简单对象,无嵌套 | 手动 clone | 性能最好 |
| 复杂对象,多层嵌套 | 序列化 | 自动处理所有层级 |
| 需要与前端交互 | JSON | 一举两得 |
| 防御性拷贝 | 拷贝构造器 | 代码直观 |
| 集合拷贝 | Stream + 深拷贝 | 灵活控制 |
---
### **8.3 防御性拷贝**
```java
/**
* 防御性拷贝:保护内部状态不被外部修改
*/
public class ImmutablePerson {
private final String name;
private final Date birthDate; // Date 是可变的!
public ImmutablePerson(String name, Date birthDate) {
this.name = name;
// 防御性拷贝:复制传入的参数
this.birthDate = new Date(birthDate.getTime());
}
public Date getBirthDate() {
// 防御性拷贝:返回副本而非原对象
return new Date(birthDate.getTime());
}
}
```
### **8.4 速查表**
| **对比项** | **引用拷贝** | **浅拷贝** | **深拷贝** |
| --- | --- | --- | --- |
| 新对象 | ❌ | ✅ | ✅ |
| 基本类型独立 | ❌ | ✅ | ✅ |
| 引用类型独立 | ❌ | ❌ | ✅ |
| 实现难度 | 无 | 简单 | 复杂 |
| 性能 | 最快 | 快 | 较慢 |
---
### **8.5 记忆口诀**
```mermaid
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart TB
%% 核心分类
Root(["Java/JS 对象拷贝记忆口诀"])
subgraph RefGroup ["引用拷贝 (Reference Copy)"]
direction TB
R1["复制地址,同一对象"]
R2[["两个名字,一个人"]]
end
subgraph ShallowGroup ["浅拷贝 (Shallow Copy)"]
direction TB
S1["新皮旧馅,表面功夫"]
S2["房子是新的,家具是共享的"]
S3["基本类型复制值,引用类型复制地址"]
end
subgraph DeepGroup ["深拷贝 (Deep Copy)"]
direction TB
D1["彻底独立,完全分家"]
D2["房子是新的,家具也全是新的"]
D3["递归复制,层层独立"]
end
subgraph StrategyGroup ["选择口诀 (Strategy)"]
direction LR
ST1["只读引用,修改要拷贝"]
ST2["简单浅拷贝,嵌套深拷贝"]
ST3["序列化最省心,手动写最性能"]
end
%% 连接关系
Root ==> RefGroup
Root ==> ShallowGroup
Root ==> DeepGroup
RefGroup ~~~ StrategyGroup
ShallowGroup ==> StrategyGroup
DeepGroup ==> StrategyGroup
%% 样式定义
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
class Root main;
class R1,R2 main;
class S1,S2,S3 decision;
class D1,D2,D3 term;
class ST1,ST2,ST3 storage;
```
---
### **8.6 核心要点图**
```mermaid
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#fdfdfd"
},
"flowchart": { "curve": "basis", "htmlLabels": true }
}}%%
graph TB
%% 核心分类
subgraph Core ["1. 本质区别 (Copy Types)"]
Type1["引用拷贝
仅复制指针,指向同一内存地址"]
Type2["浅拷贝
创建新对象,但内部引用仍共享"]
Type3["深拷贝
递归复制,完全独立的副本"]
end
%% 实现路径
subgraph Implementation ["2. 实现方式 (Implementation)"]
direction LR
Method1[["Object.clone() 默认方式"]]
subgraph DeepMethods ["深拷贝具体手段"]
M2["手动递归 Clone"]
M3["序列化 / 反序列化"]
M4["JSON 转换"]
M5["拷贝构造器"]
end
end
%% 注意事项
subgraph Precautions ["3. 开发注意事项 (Best Practices)"]
Note1("必须实现 Cloneable 接口")
Note2("String 等不可变对象无需深拷贝")
Note3("数组 clone 对引用元素仍是浅拷贝")
Note4("复杂对象推荐序列化方式")
end
%% 逻辑连接
Type2 -.-> Method1
Type3 -.-> DeepMethods
Method1 ==> Note1
DeepMethods ==> Note4
%% 样式定义
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
class Type1,Type2,Type3 main;
class Method1,M2,M3,M4,M5 decision;
class Note1,Note2,Note3,Note4 term;
```